#include <iostream>
#include <fcntl.h>

#include "ProtoSockBase.h"
#include "ProtoDispatch.h"
#include "BrickClient.h"
#include "base.h"
#include "ProtoInc.h"
#include "LogicClientManager.h"

using namespace std;
using namespace google::protobuf;

int BrickClient::CreateClient()
{
	Socket * client = new SocketClient;

    int fd = client->CreateSock("127.0.0.1", 18888);

	if (-1 == fd)
	{
		cerr<<"创建客户端失败"<<endl;
		return 1;
	}
	
	//准备给客户端发送信息
	ProcessConnect(fd);
	
	return 0;	
}

int BrickClient::ProcessConnect(unsigned fd)
{
	//ready to recv server's message
    //使用epoll
    fcntl(fd, F_SETFL, O_NONBLOCK);
    //监控连接字的读取
    epoll_event event;
    event.events = EPOLLIN|EPOLLET;
	event.data.fd = fd;

    //将连接套接字放入事件中
    //多线程处理
    int ret = poll.AddEpollEvent(fd, &event);

    if (ret)
    {
        cerr<<"add fd["<<fd<<"] to event failed"<<endl;
        return 1;
    }
	

    LogicClientManager::GetInstance()->SetFd(fd);

    //先发送登录请求
    LogicClientManager::GetInstance()->BeginLogin();

    while(1)
    {
        int ret = poll.WaitEvent(pevent);

        if (-1 == ret)
        {
            cerr<<"超时，继续等待"<<endl;
            continue;
        }
		
		for(int i = 0; i < ret; ++i)
		{
			//ready to get all standby epoll event
			//poll are same, so, we check fd

			if (pevent[i].data.fd == fd)
			{
				//ready to recv msg	
				//打算调整为一次性把消息都读取出来，那么，读取出来之后如何处理多个消息呢？
				//ProtoSockBase不应涉及具体的逻辑处理，只负责提取消息，得到消息集合
				vector<Message *> msglist;
				int ret = ProtoSockBase::ReceiveProto(fd, msglist);

				if (ret == sock_close)
				{
					//服务器异常中端
                    cout<<"服务器异常关闭"<<endl;
                    ProtoSockBase::PrintPeerName(fd);
                    //关闭对应的连接套接字
					close(fd);

					return 0;
				}
				else if (ret)
				{
                    switch(ret)
                    {
                        case wrong_type_msg : cerr<<"报文类型错误"<<endl; break;
                        case data_error_msg : cerr<<"消息数据错误，缺少必填字段"<<endl; break;
                    }
				}

				//响应消息非空
				for (int i = 0; i < msglist.size(); ++i)
				{
					//调用消息处理函数
					cout<<"收到新消息的请求，协议类型是:"<<msglist[i]->GetTypeName()<<endl;

					LogicClientManager::GetInstance()->OnMessage(msglist[i], NULL);
				}
			}
		}
    }

	return 0;
}

int main()
{
    BrickClient client;

    client.CreateClient();

    return 0;
}
